﻿using GalaSoft.MvvmLight;
using System.Collections.Generic;
using GameEngine.PDNParser;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.ObjectModel;
using GalaSoft.MvvmLight.Messaging;
using DaphneProfiBase;
using System;
using GalaSoft.MvvmLight.Command;

namespace DaphneForms.ViewModel
{
    /// <summary>
    /// PDN Filter Form View Model
    /// </summary>
    public class PDNFilterFormVM : ViewModelBase
    {
        /// <summary>
        /// Editing control type of value of the PDN Key
        /// </summary>
        public enum eControlType { RawText, Date, ResultCombo };

        // control key constants
        private const int keyNoControl = 0;
        private const int keyTextControl = 1;
        private const int keyComboControl = 2;
        private const int keyDateControl = 3;

        private PDNKey _selectedKey = null;

        private string _currentEditorValue = string.Empty;

        private PDNLibraryFilter _libraryFilter;


        /// <summary>
        /// Collection initializer of supported PDN keys
        /// </summary>
        internal List<PDNKey> _searchKeys = new List<PDNKey>()
        {
            new PDNKey { Key = PDNHeaderKey.Event, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Site, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Date, ControlType = eControlType.Date},
            new PDNKey { Key = PDNHeaderKey.Round, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.White, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Black, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Result, ControlType = eControlType.ResultCombo},
            new PDNKey { Key = PDNHeaderKey.WhiteTitle, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.BlackTitle, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.WhiteRating, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.BlackRating, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.WhiteNA, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.BlackNA, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.WhiteType, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.BlackType, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.EventDate, ControlType = eControlType.Date},
            new PDNKey { Key = PDNHeaderKey.EventSponsor, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Section, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Stage, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Board, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.TimeControl, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.TimeControlWhite, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.TimeControlBlack, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.WhiteTime, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.BlackTime, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.UTCTime, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.UTCDate, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Annotator, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Author, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.Publication, ControlType = eControlType.RawText },
            new PDNKey { Key = PDNHeaderKey.PublicationDate, ControlType = eControlType.Date}
        };

        /// <summary>
        /// Collection initializer for combobox of game-result types
        /// </summary>
        public ObservableCollection<string> ResultTypeList = new ObservableCollection<string>()
        {
            "1-0", "1/2-1/2", "0-1", "2-0", "1-1", "0-2", "0-0"
        };

        /// <summary>
        /// Constructor
        /// </summary>
        public PDNFilterFormVM()
        {
            PDNKeyList = new ObservableCollection<PDNKey>();
            _libraryFilter = new PDNLibraryFilter();
            FilterItems = new List<FilterRecordItem>();

            InitPDNKeyList();
            SelectedKey = null;

            ResultTypes = new List<string>();
            ResultTypes.AddRange(ResultTypeList);

            // register commands
            SetFilterCommand = new RelayCommand(() => SetFilter());
            CancelCommand = new RelayCommand(() => CancelForm());
            DeleteCommand = new RelayCommand(() => DeleteValue());
        }

        public bool Success
        { get; set; }

        public PDNLibraryFilter LibraryFilter
        {
            get
            {
                return _libraryFilter;
            }
            set
            {
                _libraryFilter = value;
                InitializeFormFromLibraryFilter();
            }
        }

        #region Binding Properties

        public RelayCommand SetFilterCommand
        { get; set; }

        public RelayCommand CancelCommand
        { get; set; }
        
        public RelayCommand DeleteCommand
        { get; set; }
        
        public ObservableCollection<PDNKey> PDNKeyList
        { get; set; }

        public int VisibleControlID
        { get; set; }

        public PDNKey SelectedKey
        {
            get
            {
                return _selectedKey;
            }
            set
            {
                _selectedKey = value;
                UpdateEditControl();
            }
        }

        public List<string> ResultTypes
        { get; set; }


        public string TextValue
        {
            get
            {
                return _currentEditorValue;
            }
            set
            {
                _currentEditorValue = value;
                UpdatePDNValue();
            }
        }

        public DateTime? DateValue
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_currentEditorValue))
                    return null;
                DateTime dt;
                DateTime.TryParse(_currentEditorValue, out dt);
                return dt;
            }
            set
            {
                _currentEditorValue = value.Value.ToString("yyyy.MM.dd");
                UpdatePDNValue();
            }
        }

        public string ResultValue
        {
            get
            {
                return _currentEditorValue;
            }
            set
            {
                _currentEditorValue = value;
                UpdatePDNValue();
            }
        }

        public List<FilterRecordItem> FilterItems
        { get; set; }       

        #endregion

        private void SetFilter()
        {
            // set success value
            Success = true;

            // close form
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.CloseForm));
        }

        private void CancelForm()
        {
            // cancel success
            Success = false;

            // close the form
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.CloseForm));           
        }

        /// <summary>
        /// Initialize form from the given library filter
        /// </summary>
        private void InitializeFormFromLibraryFilter()
        {
            foreach (var pair in _libraryFilter)
            {
                var keyItem = PDNKeyList.FirstOrDefault(i => i.Key == pair.Key);
                if (keyItem != null)
                    keyItem.Value = pair.Value;
            }

            // update the filter settings
            UpdateLibraryFilter();

            // refresh datagrid
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.ResetDataGrid));
        }


        /// <summary>
        /// Handler method for deleting the current value
        /// </summary>
        private void DeleteValue()
        {
            // set the empty value
            _currentEditorValue = string.Empty;

            // update the controls - order of calls of following methods is important!!!!
            UpdatePDNValue();
            UpdateEditControl();
        }

        private void UpdateFilterView()
        {
            FilterItems.Clear();

            // convert model
            foreach (var pair in _libraryFilter)
            {
                FilterItems.Add(new FilterRecordItem(pair.Key, pair.Value));
            }

            RaisePropertyChanged("FilterItems");
        }

        /// <summary>
        /// Updates library filter
        /// </summary>
        private void UpdateLibraryFilter()
        {
            _libraryFilter.Clear();

            // iterate through set values
            foreach (var key in PDNKeyList)
            {
                if (string.IsNullOrWhiteSpace(key.Value) == false)
                {
                    _libraryFilter[key.Key] = key.Value.Trim();
                }
            }

            // update the view
            UpdateFilterView();
        }

        /// <summary>
        /// Updates the PDN value in the grid
        /// </summary>
        private void UpdatePDNValue()
        {
            // if nothing selected, exit
            if (_selectedKey == null)
                return;

            // update the value
            _selectedKey.Value = _currentEditorValue;

            // update the filter settings
            UpdateLibraryFilter();

            // refresh datagrid
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.ResetDataGrid));
        }

        /// <summary>
        /// Resolve visible edit control
        /// </summary>
        private void UpdateEditControl()
        {
            if (_selectedKey == null)
            {
                VisibleControlID = keyNoControl;
            }
            else
            {
                // update editor value
                _currentEditorValue = _selectedKey.Value;

                switch (_selectedKey.ControlType)
                {
                    case eControlType.RawText:
                        VisibleControlID = keyTextControl;
                        RaisePropertyChanged("TextValue");
                        break;
                    case eControlType.Date:
                        VisibleControlID = keyDateControl;
                        RaisePropertyChanged("DateValue");
                        break;
                    case eControlType.ResultCombo:
                        VisibleControlID = keyComboControl;
                        RaisePropertyChanged("ResultTypes");
                        RaisePropertyChanged("ResultValue");
                        break;
                }
            }

            RaisePropertyChanged("VisibleControlID");
        }


        /// <summary>
        /// Initializes PDN Key List
        /// </summary>
        private void InitPDNKeyList()
        {
            // copy from the source
            foreach (var item in _searchKeys)
            {
                PDNKeyList.Add(new PDNKey(item.Key, item.ControlType));
            }                      

            // notify the change
            RaisePropertyChanged("PDNKeyList");
        }

        /// <summary>
        /// Binding class for the datagrid
        /// </summary>
        public class PDNKey
        {
            public string Key
            { get; set; }

            public string Value
            { get; set; }

            public eControlType ControlType
            { get; set; }

            public PDNKey()
            {
            }            

            public PDNKey(string key, eControlType controlType)
            {
                Key = key;
                Value = string.Empty;
                ControlType = controlType;
            }
        }

        /// <summary>
        /// Filter settings item record
        /// </summary>
        public class FilterRecordItem
        {
            public string Key
            { get; set; }

            public string Value
            { get; set; }

            public FilterRecordItem(string key, string value)
            {
                Key = key;
                Value = value;
            }
        }           
    }
}